package org.rency.common.redis.annotation.advice;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import javax.annotation.Resource;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.rency.common.redis.annotation.RCacheData;
import org.rency.common.redis.annotation.RCacheDomain;
import org.rency.common.redis.service.RedisService;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(1000)
public class RedisCacheDataAdvice<T> extends RCacheAdviceBase<Object> {
	
	@Resource(name="defaultRedisTemplateService")
	private RedisService<String, Object> redisService;

	@Pointcut("@annotation(org.rency.common.redis.annotation.RCacheData)")
    private void cacheData() {}
	
	@SuppressWarnings("unchecked")
	@Around("cacheData()")
	public Object aroundCacheData(ProceedingJoinPoint pjp) throws Throwable {
		long startTime = System.currentTimeMillis();
		T ret = null;
		RCacheDomain<Object> domain = null;
		
		try {
            Method currentMethod = getCurrentMethod(pjp);
            Annotation annotation = getMethodAnnotation(currentMethod, RCacheData.class);
            domain = buildCacheKey(pjp, currentMethod, annotation);
            if(domain == null){
            	throw new RuntimeException("redis cache annotation error !");
            }
            domain.setCacheData(getCacheData(pjp, annotation));
        } catch (Throwable t) {
        	logger.warn("redis cache aop inner error！", t);
        }
		try {
			redisService.remove(domain.getCacheKey());
			ret = (T) pjp.proceed(pjp.getArgs());
			if (ret != null) {
				redisService.set(domain.getCacheKey(),domain.getCacheData(),domain.getExpireTime());
            }
		} catch (Throwable t) {
         	logger.warn("redis cache aop inner error，can not cache data！", t);
        }finally{
        	long endTime = System.currentTimeMillis();
     		logger.info("put cache data use :{}ms, key:{}", (endTime - startTime), domain.getCacheKey()); 
        }
		return ret;
	}
	
}
